#pragma once
#include "ellipse.h"
#ifdef _WIN32
    // Windows 平台（32位或64位）
    #define IS_WINDOWS_PLATFORM 1
#else
    // 非 Windows 平台
    #define IS_WINDOWS_PLATFORM 0
#endif
// winows 平台使用这个函数

#ifdef IS_WINDOWS_PLATFORM
#include <windows.h>    // 提供 Windows API
#include <wincrypt.h>   // 提供加密相关函数
#endif
/**
* Parameter Constant
*/
const sm2_uint256_t Prime = {
    0xFFFFFFFE, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF
};
const uint8_t param_A[32] = {
                0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
                0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, };


const uint8_t param_B[32] = {
                0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,0x9E,0x4B,0xCF,0x65,0x09,0xA7,
                0xF3,0x97,0x89,0xF5,0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,0x0E,0x93, };


const sm2_point_t param_G = {
    .x = {0x32C4AE2C,0x1F198119, 0x5F990446,0x6A39C994,
          0x8FE30BBF,0xF2660BE1, 0x715A4589,0x334C74C7,},
    .y = {0xBC3736A2,0xF4F6779C, 0x59BDCEE3,0x6B692153,
          0xD0A9877C,0xC62A4740, 0x02DF32E5,0x2139F0A0,} };

const sm2_uint256_t param_N = {
            0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
            0x7203DF6B, 0x21C6052B, 0x53BBF409, 0x39D54123
};

const sm2_uint256_t P_NEG_INV = {
    0xfffffffc, 0x00000001,
    0xfffffffe, 0x00000000,
    0xffffffff, 0x00000001,
    0x00000000, 0x00000001
};
const uint32_t N_NEG_INV[8] = {
    0x6f39132f, 0x82e4c7bc,
    0x2b0068d3, 0xb08941d4,
    0xdf1e8d34, 0xfc8319a5,
    0x327f9e88, 0x72350975

};
const uint32_t N_2_512_mod_n[8] = {
    0x1eb5e412, 0xa22b3d3b,  0x620fc84c, 0x3affe0d4, 0x3464504a, 0xde6fa2fa, 0x901192af, 0x7c114f20
};
const uint32_t N_2_512_mod_p[8] = {
    0x00000004, 0x00000002,  0x00000001, 0x00000001, 0x00000002, 0xffffffff, 0x00000002, 0x00000003
};

const sm2_point_t ZERO_POINT = {
    .x = {0,0,0,0,0,0,0,0},
    .y = {0,0,0,0,0,0,0,0},
};

// 引入256位数做计算  数据存储为大端存储  高位---------低位
const sm2_uint256_t N_256_1 = { 0,0,0,0,0,0,0,1 };
//const sm2_uint256_t N_256_1 = { 1,0,0,0,0,0,0,0 };
const sm2_uint256_t N_256_ZERO = { 0,0,0,0,0,0,0,0 };

/**
 * Convert the uint8_t array back to the uint32_t array
 *
 * @param src uint32_t array to be converted
 * @param dst uint8_t array of the conversion
 */
void convert_to_uint32(uint8_t src[32], uint32_t dst[8]) {
    if (src == NULL || dst == NULL) {
        // Handle error (e.g., return or log error)
        return;
    }

    for (size_t i = 0; i < 8; i++) {
        uint32_t value = 0;
        for (size_t j = 0; j < 4; j++) {
            value = (value << 8) | src[i * 4 + j];
        }
        dst[i] = value;
    }
}

/**
 * Convert the uint32_t array back to the uint8_t array
 *
 * @param src uint8_t array to be converted
 * @param dst uint32_t array of the conversion
 */
void convert_to_uint8(uint32_t src[8], uint8_t dst[32]) {
    if (src == NULL || dst == NULL) {
        return;
    }

    for (size_t i = 0; i < 8; i++) {
        for (size_t j = 0; j < 4; j++) {
            dst[i * 4 + j] = (src[i] >> (24 - j * 8)) & 0xFF;
        }
    }
}

/**
 * Convert number from the natural domain to number in the Montgomery domain(N)
 *
 * @param src uint32_t array in natural domain to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst uint32_t array in Montgomery domain of the conversion
 */
void n_num2mgmy(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8])
{
    if (src == NULL || dst == NULL) {
        return;
    }
    n_mod_mul(src, N_2_512_mod_n, p, dst);
}

/**
 * Convert number from the Montgomery domain(N) to number in the natural domain
 *
 * @param src uint32_t array in Montgomery domain(N) to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst uint32_t array in natural domain of the conversion
 */
void n_mgmy2num(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8])
{
    if (src == NULL || dst == NULL) {
        return;
    }
    n_mod_mul(src, N_256_1, p, dst);
}

/**
 * Convert number from the natural domain to number in the Montgomery domain(P)
 *
 *
 * @param src uint32_t array in natural domain to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst uint32_t array in Montgomery domain of the conversion
 */
void num2mgmy(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8])
{
    if (src == NULL || dst == NULL) {
        return;
    }
    mod_mul(src, N_2_512_mod_p, p, dst);
}

/**
 * Convert number from the Montgomery domain(N) to number in the natural domain
 *
 * @param src uint32_t array in Montgomery domain(N) to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst uint32_t array in natural domain of the conversion
 */
void mgmy2num(uint32_t src[8], sm2_uint256_t p, uint32_t dst[8])
{
    if (src == NULL || dst == NULL) {
        return;
    }
    mod_mul(src, N_256_1, p, dst);
}

/**
 * Convert point from the natural domain to number in the Montgomery domain
 *
 *
 * @param src point in natural domain to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst point in Montgomery domain of the conversion
 */
void point_modp2mgmy(sm2_point_t* src, sm2_uint256_t p, sm2_point_t* dst) {
    if (src == NULL || dst == NULL) {
        return;
    }
    num2mgmy(src->x, p, dst->x);
    num2mgmy(src->y, p, dst->y);
}

/**
 * Convert point from the Montgomery domain to number in the natural domain
 *
 * @param src point in Montgomery domain to be converted
 * @param p prime which needed from Montgomery domain
 * @param dst point in natural domain of the conversion
 */
void mgmy_modp2point(sm2_point_t* src, sm2_uint256_t p, sm2_point_t* dst) {
    if (src == NULL || dst == NULL) {
        return;
    }
    mgmy2num(src->x, p, dst->x);
    mgmy2num(src->y, p, dst->y);
}

/**
 * Take the lower 256 bits of 512 digits
 *
 * @param src 512 digits
 * @param dst Low 256 bits of src
 */
void sm2_getlow256(sm2_uint512_t src, sm2_uint256_t dst) {
    if (src == NULL || dst == NULL) {
        return;
    }
    for (int i = 8; i < 16; i++)
    {
        dst[i - 8] = src[i];
    }
}

/**
 * Take the higher 256 bits of 512 digits
 *
 * @param src 512 digits
 * @param dst high 256 bits of src
 */
void sm2_gethigh256(sm2_uint512_t src, sm2_uint256_t dst) {
    if (src == NULL || dst == NULL) {
        return;
    }
    for (int i = 0; i < 8; i++)
    {
        dst[i] = src[i];
    }
}

/**
 * Compare the size of 256 bits, compare every 32 bits.
 *
 * @Return  a>b return 1；a<b return -1；a=b return 0
 */
int compare_value(sm2_uint256_t a, sm2_uint256_t b) {
    for (int i = 0; i < 8; i++)
    {
        if (a[i] > b[i])
            return 1;
        else if (a[i] < b[i])
            return -1;
    }
    return 0;
}

/**
 * Copy between four bytes element arrays
 */
void copy(sm2_uint256_t src, sm2_uint256_t dst) {
    memcpy(dst, src, sizeof(sm2_uint256_t));
}

/**
 * Invert each element of P
 */
void neg_p(sm2_uint256_t result, const sm2_uint256_t p) {
    // 对 P 每个元素进行取反
    for (int i = 0; i < 8; i++) {
        result[i] = ~p[i];
    }

    // 加 1 处理，从最低有效位开始
    uint32_t carry = 1;
    for (int i = 7; i >= 0 && carry != 0; i--) {
        uint32_t sum = result[i] + carry;
        result[i] = sum;
        carry = (sum < carry);  // 如果发生溢出，则继续进位
    }
}


/**
 * Addition and modulo operation of two numbers
 *
 * @param a addend number 1
 * @param b addend number 2
 * @param p prime
 * @param result the result of adding two numbers and taking the modulus
 */
void mod_add(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result) {

    uint32_t carry = add(a, b, result);

    // 发生进位 
    if (carry != 0)
    {
        sm2_uint256_t np;
        neg_p(np, p);
        add(np, result, result);
    }
    else {
        // 没有进位, 做取模处理
        while (compare_value(result, p) >= 0) {
            sub(result, p, result);
        }
    }

}

/**
 * Ordinary addition
 */
uint32_t add(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t result)
{
    uint32_t carry = 0;  // 初始化进位
    for (int i = 7; i >= 0; i--) {
        uint32_t sum = a[i] + b[i] + carry;  // 当前位的加法
        carry = (sum < a[i]) || (sum < b[i] && carry);  // 检测是否进位
        result[i] = sum;  // 存储结果
    }
    return carry;
}

/**
 * 512 digit addition operation
 */
uint32_t add_uint512_t(sm2_uint512_t a, sm2_uint512_t b, sm2_uint512_t result)
{
    uint32_t carry = 0;  // 初始化进位
    for (int i = 15; i >= 0; i--) {
        uint32_t sum = a[i] + b[i] + carry;  // 当前位的加法
        carry = (sum < a[i]) || (sum < b[i] && carry);  // 检测是否进位
        result[i] = sum;  // 存储结果
    }
    return carry;
}

/**
 * Subtraction and modulo operation of two numbers
 *
 * @param a minuend number
 * @param b subtrahend number
 * @param p prime
 * @param result the result of subtracting two numbers and taking the modulus
 */
void mod_sub(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result)
{
    uint32_t borrow = sub(a, b, result);
    // 有借位
    if (borrow)
    {
        sm2_uint256_t np;
        neg_p(np, p);
        sub(result, np, result);
    }
}

/**
 * Ordinary subtraction
 */
uint32_t sub(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t result)
{
    sm2_uint256_t res;
    uint32_t borrow = 0;
    uint32_t tp;
    memset(res, 0, sizeof(sm2_uint256_t));
    tp = a[7] - b[7];
    res[7] = tp;
    borrow = (tp > a[7]);
    for (int i = 6; i >= 0; i--) {
        tp = a[i] - borrow;
        borrow = (tp > a[i]);
        res[i] = tp - b[i];
        borrow += (res[i] > tp); // 检查是否需要借位
    }
    memcpy(result, res, sizeof(sm2_uint256_t));
    return borrow;
}

/**
 * Multiplying two 256 bit numbers
 *
 * @param a 256 bit number
 * @param b 256 bit number
 * @param result multiplying two 256 bit numbers yields 512 bit numbers
 */
uint32_t mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint512_t result)
{
    uint32_t temp_result[16] = { 0 };  // 存储 512 位乘积结果
    uint16_t* tr16 = (uint16_t*)temp_result;
    uint32_t carry = 0;  // 初始化进位
    // 逐位计算乘积
    int i, j;
    for (i = 0; i < 16; i++) {
        carry = 0;
        for (j = 0; j < 16; j++) {
            uint32_t ta = ((a[(15 - i) / 2] >> (((16 - i) % 2) * 16)) & 0xFFFF);
            uint32_t tb = ((b[(15 - j) / 2] >> (((16 - j) % 2) * 16)) & 0xFFFF);
            uint32_t sum = tr16[i + j] + ta * tb + carry;
            tr16[i + j] = sum & 0xFFFF;
            carry = sum >> 16;
        }
        tr16[i + 16] = carry;
    }

    for (int t = 0; t < 16; t++)
    {
        result[15 - t] = temp_result[t];
    }

    return carry;
}

/**
 * Multiplication in Montgomery Field(N)
 *
 * @param a 256 bit number
 * @param b 256 bit number
 * @param p Prime numbers in Montgomery domain(N)
 * @param result multiplying two 256 bit numbers and taking mold yields 256 bit numbers
 */
void n_mod_mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result) {
    sm2_uint512_t temp;
    sm2_uint512_t temp1;
    uint32_t carry = 0;

    mul(a, b, temp); // 计算 x

    sm2_uint256_t lowtemp;
    sm2_getlow256(temp, lowtemp);
    mul(lowtemp, N_NEG_INV, temp1); // 计算 x*n' mod R
    sm2_getlow256(temp1, lowtemp);

    mul(lowtemp, p, temp1);         // 计算 (x*n' mod R )*n
    carry = add_uint512_t(temp, temp1, temp);

    sm2_gethigh256(temp, result);

    if (carry)
    {
        sm2_uint256_t np;
        neg_p(np, p);
        add(np, result, result);
    }
    else if (compare_value(result, p) >= 0)
    {
        sub(result, p, result);
    }
}

/**
 * Multiplication in Montgomery Field(P)
 *
 * @param a 256 bit number
 * @param b 256 bit number
 * @param p Prime numbers in Montgomery domain(P)
 * @param result multiplying two 256 bit numbers and taking mold yields 256 bit numbers
 */
void mod_mul(sm2_uint256_t a, sm2_uint256_t b, sm2_uint256_t p, sm2_uint256_t result)
{
    sm2_uint512_t temp;
    sm2_uint512_t temp1;
    //sm2_uint256_t p_neg_inv;
    uint32_t carry = 0;
    //convert_to_uint32(P_NEG_INV, p_neg_inv);
    mul(a, b, temp); // 计算 x
    sm2_uint256_t lowtemp;
    sm2_getlow256(temp, lowtemp);
    mul(lowtemp, P_NEG_INV, temp1); // 计算 x*p' mod R
    sm2_getlow256(temp1, lowtemp);
    mul(lowtemp, p, temp1);         // 计算 (x*p' mod R )*p
    carry = add_uint512_t(temp, temp1, temp);

    sm2_gethigh256(temp, result);

    if (carry)
    {
        sm2_uint256_t np;
        neg_p(np, p);
        add(np, result, result);
    }
    else if (compare_value(result, p) >= 0)
    {
        sub(result, p, result);
    }

}

void n_mod_sqr(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result)
{
    n_mod_mul(a, a, p, result);
}

void mod_sqr(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result)
{
    mod_mul(a, a, p, result);
}

// 模幂：计算 a^b % p
void n_mod_fast_exp(sm2_uint256_t a, uint32_t b, sm2_uint256_t p, sm2_uint256_t result) {
    sm2_uint256_t base, res;
    // 初始化
    memcpy(base, a, sizeof(sm2_uint256_t));  // base = a
    n_num2mgmy(N_256_1, p, res);

    while (b > 0) {
        if (b & 1) {
            n_mod_mul(res, base, p, res);
        }
        n_mod_mul(base, base, p, base);  // base = base^2
        b = b >> 1;                // exp = exp / 2
    }
    memcpy(result, res, sizeof(sm2_uint256_t));
}

// 模幂：计算 a^b % p
void mod_fast_exp(sm2_uint256_t a, uint32_t b, sm2_uint256_t p, sm2_uint256_t result) {
    sm2_uint256_t base, res;
    // 初始化
    memcpy(base, a, sizeof(sm2_uint256_t));  // base = a
    num2mgmy(N_256_1, p, res);

    while (b > 0) {
        if (b & 1) {
            mod_mul(res, base, p, res);
        }
        mod_mul(base, base, p, base);  // base = base^2
        b = b >> 1;                // exp = exp / 2
    }
    memcpy(result, res, sizeof(sm2_uint256_t));
}

/**
* Model inversion operation in Montgomery Domain(N)
*/
void n_mod_inverse(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result)
{
    //printf("n_mod_inverse中的mg_key+1：\n");
    //print_uint32_array(a);
    //printf("\n");
    sm2_uint256_t p_2;

    sm2_uint256_t temp;
    sm2_uint256_t a32_1;
    sm2_uint256_t a32_2;
    sm2_uint256_t a32_3;
    sm2_uint256_t a32_4;
    sm2_uint256_t a32_5;
    sm2_uint256_t a32_6;
    sm2_uint256_t a32_7;
    sm2_uint256_t subnum2 = {
        0,0,0,0,0,0,0,0x2
    };
    sub(p, subnum2, p_2);
    n_mod_sqr(a, p, a32_1);         // a32_1  a^(2^32)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_1, p, a32_1);
    }
    // 分别先计算出a^(2^31*i)的结果
    n_mod_mul(a32_1, a32_1, p, a32_2); // a32_2  a^(2^64)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_2, p, a32_2);
    }
    n_mod_mul(a32_2, a32_2, p, a32_3); // a32_3  a^(2^96)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_3, p, a32_3);
    }
    n_mod_mul(a32_3, a32_3, p, a32_4); // a32_4  a^(2^128)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_4, p, a32_4);
    }
    n_mod_mul(a32_4, a32_4, p, a32_5); // a32_5  a^(2^160)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_5, p, a32_5);
    }
    n_mod_mul(a32_5, a32_5, p, a32_6); // a32_6  a^(2^192)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_6, p, a32_6);
    }
    n_mod_mul(a32_6, a32_6, p, a32_7); // a32_7  a^(2^224)
    for (int i = 0; i < 31; i++)
    {
        n_mod_sqr(a32_7, p, a32_7);
    }


    // 再把结果和a^p-2[i]的结果做乘
    n_mod_fast_exp(a, p_2[7], p, temp);
    n_mod_fast_exp(a32_1, p_2[6], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_2, p_2[5], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_3, p_2[4], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_4, p_2[3], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_5, p_2[2], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_6, p_2[1], p, result);
    n_mod_mul(temp, result, p, temp);
    n_mod_fast_exp(a32_7, p_2[0], p, result);
    n_mod_mul(temp, result, p, result);

}
/**
* Model inversion operation Montgomery Domain(P)
*/
void mod_inverse(sm2_uint256_t a, sm2_uint256_t p, sm2_uint256_t result)
{
    sm2_uint256_t p_2;

    sm2_uint256_t temp;
    sm2_uint256_t a32_1;
    sm2_uint256_t a32_2;
    sm2_uint256_t a32_3;
    sm2_uint256_t a32_4;
    sm2_uint256_t a32_5;
    sm2_uint256_t a32_6;
    sm2_uint256_t a32_7;
    sm2_uint256_t subnum2 = {
        0,0,0,0,0,0,0,0x2
    };
    sub(p, subnum2, p_2);
    mod_sqr(a, p, a32_1);         // a32_1  a^(2^32)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_1, p, a32_1);
    }
    // 分别先计算出a^(2^31*i)的结果
    mod_mul(a32_1, a32_1, p, a32_2); // a32_2  a^(2^64)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_2, p, a32_2);
    }
    mod_mul(a32_2, a32_2, p, a32_3); // a32_3  a^(2^96)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_3, p, a32_3);
    }
    mod_mul(a32_3, a32_3, p, a32_4); // a32_4  a^(2^128)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_4, p, a32_4);
    }
    mod_mul(a32_4, a32_4, p, a32_5); // a32_5  a^(2^160)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_5, p, a32_5);
    }
    mod_mul(a32_5, a32_5, p, a32_6); // a32_6  a^(2^192)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_6, p, a32_6);
    }
    mod_mul(a32_6, a32_6, p, a32_7); // a32_7  a^(2^224)
    for (int i = 0; i < 31; i++)
    {
        mod_sqr(a32_7, p, a32_7);
    }


    // 再把结果和a^p-2[i]的结果做乘
    mod_fast_exp(a, p_2[7], p, temp);
    mod_fast_exp(a32_1, p_2[6], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_2, p_2[5], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_3, p_2[4], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_4, p_2[3], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_5, p_2[2], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_6, p_2[1], p, result);
    mod_mul(temp, result, p, temp);
    mod_fast_exp(a32_7, p_2[0], p, result);
    mod_mul(temp, result, p, result);

}

/**
* Judge if the data is 0
*/
bool is_zero(uint32_t* r)
{
    if (r == NULL)
        return false;
    for (int i = 0; i < 8; i++)
    {
        if (r[i] != 0)
            return false;
    }
    return true;
}

/**
* Compare two uint32_t number
*/
bool compare(uint8_t* r, uint8_t* k, size_t len)
{
    if (r == NULL || k == NULL || len <= 0)
        return false;
    return memcmp(r, k, len);
}

bool is_in_N(uint32_t* r) {
    // 判断 r 是否 >= 1
    if (r[0] == 0 && memcmp(r, (uint32_t[8]) { 0 }, 8) == 0) {
        return false;  // 如果 r 是零
    }

    // 判断 r 是否 < n
    if (compare_value(param_N, r)) {
        return true;
    }

    return false;
}

/**
 * Add two points
 *
 * @param a、b points in the Montgomery domain
 * @param p Prime numbers in Montgomery domain
 * @param result the result of add two points
 */
void point_add(const sm2_point_t* a, const sm2_point_t* b, sm2_uint256_t p, sm2_point_t* r)
{
    sm2_uint256_t lambda, x1, y1, x2, y2, x3, y3;

    // 取出 P 和 Q 的坐标
    copy(a->x, x1);
    copy(a->y, y1);
    copy(b->x, x2);
    copy(b->y, y2);

    if (compare_value(x1, N_256_ZERO) == 0 && compare_value(y1, N_256_ZERO) == 0)
    {
        memcpy(r->x, x2, sizeof(x2));  // 将 x3 的值赋给 R->x
        memcpy(r->y, y2, sizeof(y2));  // 将 y3 的值赋给 R->y
        return;
    }
    if (compare_value(x2, N_256_ZERO) == 0 && compare_value(y2, N_256_ZERO) == 0)
    {
        memcpy(r->x, x1, sizeof(x1));  // 将 x3 的值赋给 R->x
        memcpy(r->y, y1, sizeof(y1));  // 将 y3 的值赋给 R->y
        return;
    }

    if (compare_value(x1, x2) == 0 && compare_value(y1, y2) == 0)
    {
        point_double(a, p, r);
        return;
    }


    // 计算 λ = (y2 - y1) / (x2 - x1) (mod p)
    sm2_uint256_t x2_minus_x1, y2_minus_y1;
    mod_sub(x2, x1, p, x2_minus_x1);  // x2 - x1
    mod_sub(y2, y1, p, y2_minus_y1);  // y2 - y1

    sm2_uint256_t denominator_inv;
    mod_inverse(x2_minus_x1, p, denominator_inv);  // inv(x2 - x1) (mod p)

    mod_mul(denominator_inv, y2_minus_y1, p, lambda);  // lambda = (y2 - y1) * inv(x2 - x1) (mod p)


    // 计算 x3 = λ^2 - x1 - x2 (mod p)
    sm2_uint256_t lambda_square;
    mod_sqr(lambda, p, lambda_square);  // λ^2
    //printf("x3\n");
    //print_uint32_array(lambda_square);

    mod_sub(lambda_square, x1, p, x3);
    //printf("x3_0\n");
    //print_uint32_array(x3);
    //printf("x2\n");
    //print_uint32_array(x2); // x3 = λ^2 - x1 (mod p)
    mod_sub(x3, x2, p, x3);  // x3 = x3 - x2 (mod p)
    //printf("x3\n");
    //print_uint32_array(x3);

    // 计算 y3 = λ(x1 - x3) - y1 (mod p)
    sm2_uint256_t x1_minus_x3;
    mod_sub(x1, x3, p, x1_minus_x3);  // x1 - x3
    mod_mul(lambda, x1_minus_x3, p, y3);  // λ * (x1 - x3)
    mod_sub(y3, y1, p, y3);  // y3 = λ * (x1 - x3) - y1

    // 将结果保存到 R 中
    memcpy(r->x, x3, sizeof(x3));  // 将 x3 的值赋给 R->x
    memcpy(r->y, y3, sizeof(y3));  // 将 y3 的值赋给 R->y
}

// 不能对0做double
void point_double(const sm2_point_t* a, sm2_uint256_t p, sm2_point_t* r) {
    sm2_uint256_t lambda, x1, y1, x3, y3, pa;
    sm2_uint256_t num_3 = { 0,0,0,0,0,0,0,3 };
    sm2_uint256_t num_2 = { 0,0,0,0,0,0,0,2 };

    // 取出 P 的坐标
    copy(a->x, x1);
    copy(a->y, y1);

    convert_to_uint32(param_A, pa);
    num2mgmy(pa, p, pa);

    // todo 这里可以用硬编码 减少计算
    num2mgmy(num_2, p, num_2);
    num2mgmy(num_3, p, num_3);

    // 计算 λ = (3 * x1^2 + a) / (2 * y1) (mod p)
    sm2_uint256_t x1_square, three_x1_square;
    mod_sqr(x1, p, x1_square);  // x1^2
    mod_mul(x1_square, num_3, p, three_x1_square);  // 3 * x1^2
    mod_add(three_x1_square, pa, p, three_x1_square);  // 3 * x1^2 + a
    sm2_uint256_t two_y1;
    mod_mul(y1, num_2, p, two_y1);  // 2 * y1

    sm2_uint256_t denominator_inv;
    mod_inverse(two_y1, p, denominator_inv);  // inv(2 * y1) (mod p)
    mod_mul(denominator_inv, three_x1_square, p, lambda);  // λ = (3 * x1^2 + a) * inv(2 * y1) (mod p)

    // 计算 x3 = λ^2 - 2 * x1 (mod p)
    sm2_uint256_t lambda_square;
    mod_sqr(lambda, p, lambda_square);  // λ^2
    sm2_uint256_t two_x1;
    mod_mul(x1, num_2, p, two_x1);  // 2 * x1
    mod_sub(lambda_square, two_x1, p, x3);  // x3 = λ^2 - 2 * x1 (mod p)


    // 计算 y3 = λ(x1 - x3) - y1 (mod p)
    sm2_uint256_t x1_minus_x3;
    mod_sub(x1, x3, p, x1_minus_x3);  // x1 - x3
    mod_mul(lambda, x1_minus_x3, p, y3);  // λ * (x1 - x3)
    //print_uint32_array(y3);
    //print_uint32_array(y1);
    mod_sub(y3, y1, p, y3);  // y3 = λ * (x1 - x3) - y1
    //print_uint32_array(y3);

    // 将结果保存到 R 中
    memcpy(r->x, x3, sizeof(x3));  // 将 x3 的值赋给 R->x
    memcpy(r->y, y3, sizeof(y3));  // 将 y3 的值赋给 R->y
}

/**
 * Multiply a point by a number
 *
 * Note: K does not need to be converted to Montgomery domain
 *
 * @param P a point in the Montgomery domain
 * @param k integer in the natural domain
 * @param p Prime numbers in Montgomery domain
 * @param result the result of multiplying a point and a number
 */
void point_multiply(const sm2_point_t* P, const sm2_uint256_t k, sm2_uint256_t p, sm2_point_t* R)
{
    // todo 可以优化
    sm2_point_t temp_point;
    sm2_point_t Q;
    memset(&Q, 0, sizeof(sm2_point_t)); // 无穷远点 (0, 0)

    copy(Q.x, temp_point.x);
    copy(Q.y, temp_point.y);

    // 从最高位开始，逐位处理标量 k
    for (int i = 255; i >= 0; i--) {
        // 每次都做点的倍加
        point_double(&Q, p, &Q);
        mgmy_modp2point(&Q, p, &Q);
        point_modp2mgmy(&Q, p, &Q);
        if (i == 255)
        {
            copy(P->x, Q.x);
            copy(P->y, Q.y);
        }
        // 判断标量当前位是否为1
        if (k[(i / 32)] >> (31 - (i % 32)) & 1) {
            // 如果当前位是1，就进行点加法
            if (i == 255)
            {
                point_add(&ZERO_POINT, P, p, &temp_point);
            }
            else {
                point_add(&Q, &temp_point, p, &temp_point);
            }

        }
    }

    // 返回结果
    memcpy(R, &temp_point, sizeof(sm2_point_t));
}

#ifdef IS_WINDOWS_PLATFORM

int random_generate(sm2_uint256_t buffer){
    HCRYPTPROV hCryptProv;
    size_t len = 32;

    if (!buffer || !CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        return -1;
    }
    uint8_t _8b_buffer[32];
    if (CryptGenRandom(hCryptProv, (DWORD)len, _8b_buffer) != TRUE) {
        CryptReleaseContext(hCryptProv, 0);
        convert_to_uint32(_8b_buffer, buffer);
        return -1;
    }

    CryptReleaseContext(hCryptProv, 0);
    convert_to_uint32(_8b_buffer, buffer);
    return 1;
}

#endif


void print_sm2_uint256_t(sm2_uint256_t num) {
    printf("random_k = { ");
    for (int i = 0; i < 8; i++) {
        printf("0x%08X", num[i]);
        if (i < 7) {
            printf(", ");
        }
    }
    printf(" }\n");
}


/**
* Print point coordinates
*/
void print_point(const sm2_point_t* Point)
{
    printf("Point x: ");
    print_uint32_array(Point->x);
    printf("\nPoint y: ");
    print_uint32_array(Point->y);
    printf("\n");
}

/**
* Print the hexadecimal representation of the uint32_t array which has 8 elements
*/
void print_uint32_array(uint32_t arr[8]) {
    for (int i = 0; i < 8; i++) {
        printf("%08x ", arr[i]);
    }
    printf("\n");
}

/**
* Print the hexadecimal representation of the uint32_t array which has 16 elements
*/
void print_uint512_array(sm2_uint512_t arr) {
    for (int i = 0; i < 16; i++) {
        printf("%08x ", arr[i]);
    }
    printf("\n");
}

/**
* Print the hexadecimal representation of the uint8_t array which has 32 elements
*/
void print_uint8_array(uint8_t arr[32]) {
    for (int i = 0; i < 32; i++) {
        printf("%02x", arr[i]);
    }
    printf("\n");
}